﻿using System;
using System.Linq;
using Newtonsoft.Json.Linq;

namespace Xenta.Utils
{
    /// <summary>
    /// Contains the helper methods for a JSON.NET 
    /// based dynamic model.
    /// </summary>
    public static class JDM
    {
        /// <summary>
        /// Converts the JToken value to the required type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <typeparam name="T">The required type.</typeparam>
        /// <returns>The converted value or a default value.</returns>
        public static T As<T>(dynamic value)
        {
            if(value == null)
                return default(T);
            if(value is T)
                return value;
            var jt = value as JToken;
            if(jt == null)
                return default(T);
            return jt.ToObject<T>();
        }

        /// <summary>
        /// Converts the JToken value to the String type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The converted value or a default value.</returns>
        public static string String(dynamic value)
        {
            return As<String>(value);
        }

        /// <summary>
        /// Converts the JToken value to the Boolean type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The converted value or a default value.</returns>
        public static bool Boolean(dynamic value)
        {
            return As<Boolean>(value);
        }

        /// <summary>
        /// Converts the JToken value to the Decimal type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The converted value or a default value.</returns>
        public static decimal Decimal(dynamic value)
        {
            return As<Decimal>(value);
        }

        /// <summary>
        /// Converts the JToken value to the Guid type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The converted value or a default value.</returns>
        public static Guid Guid(dynamic value)
        {
            return As<Guid>(value);
        }

        /// <summary>
        /// Converts the JToken value to the DateTime type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The converted value or a default value.</returns>
        public static DateTime DateTime(dynamic value)
        {
            return As<DateTime>(value);
        }

        /// <summary>
        /// Converts the JToken value to the Byte type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The converted value or a default value.</returns>
        public static byte Byte(dynamic value)
        {
            return As<Byte>(value);
        }

        /// <summary>
        /// Converts the JToken value to the Int16 type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The converted value or a default value.</returns>
        public static short Int16(dynamic value)
        {
            return As<Int16>(value);
        }

        /// <summary>
        /// Converts the JToken value to the Int32 type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The converted value or a default value.</returns>
        public static int Int32(dynamic value)
        {
            return As<Int32>(value);
        }

        /// <summary>
        /// Converts the JToken value to the Int64 type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The converted value or a default value.</returns>
        public static long Int64(dynamic value)
        {
            return As<Int64>(value);
        }

        /// <summary>
        /// Converts the JToken value to the Single type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The converted value or a default value.</returns>
        public static double Single(dynamic value)
        {
            return As<Single>(value);
        }

        /// <summary>
        /// Converts the JToken value to the Double type.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The converted value or a default value.</returns>
        public static double Double(dynamic value)
        {
            return As<Double>(value);
        }

        /// <summary>
        /// Determines, if a flags value contains the required flags.
        /// </summary>
        /// <param name="value">The flags value.</param>
        /// <param name="flags">The required flags.</param>
        /// <returns>true if flags found; otherwise false.</returns>
        public static bool HasFlags(dynamic value, params string[] flags)
        {
            if(flags == null || !flags.Any())
                return false;
            var tmp1 = flags.Select(x => x.Trim().ToLowerInvariant());
            var tmp2 = ((string)String(value)).Split(',')
                .Select(x => x.Trim().ToLowerInvariant())
                .Intersect(tmp1);
            return tmp2.Count() == tmp1.Count();
        }
    }
}
